package gao.xiaolei.jgit;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeCommand;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.TransportConfigCallback;
import org.eclipse.jgit.api.errors.AbortedByHookException;
import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException;
import org.eclipse.jgit.api.errors.CheckoutConflictException;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidConfigurationException;
import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.NoFilepatternException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.NoMessageException;
import org.eclipse.jgit.api.errors.NotMergedException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.RefNotAdvertisedException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.api.errors.UnmergedPathsException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.errors.StopWalkException;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.SshTransport;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import gao.xiaolei.myExcepition.MyExcepition;
import gao.xiaolei.entity.LogEnity;
import gao.xiaolei.entity.StatusList;
import gao.xiaolei.util.SshConnect;
import ch.ethz.ssh2.Connection;
import com.jcraft.jsch.Session;

@Component("Jgit")
@RefreshScope
public class Jgit implements InitializingBean {

	@Value("${gitConfig.remoteUrl}")
	private String remoteUrl;
	@Value("${gitConfig.userName}")
	private String userName;
	@Value("${gitConfig.password}")
	private String password;
	@Value("${gitConfig.remotePath}")
	private String remotePath;
	@Value("${gitConfig.localPath}")
	private String localPath;

	public Jgit() {
	}

	// 用于解决HostKey问题
	private TransportConfigCallback getTransportConfigCallback() {
		final SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
			@Override
			protected void configure(OpenSshConfig.Host host, Session session) {
				session.setConfig("StrictHostKeyChecking", "no");
			}
		};
		return new TransportConfigCallback() {

			public void configure(Transport transport) {
				if (transport instanceof TransportHttp)
					return;
				SshTransport sshTransport = (SshTransport) transport;
				sshTransport.setSshSessionFactory(sshSessionFactory);
			}
		};
	}

	/**
	 * 在非本机指定目录建立远程仓库
	 * 
	 * @throws IOException
	 * @throws MyExcepition
	 */
	public void createRemote(String remoteName) throws IOException,
			MyExcepition {
		SshConnect sc = new SshConnect(remoteUrl, userName, password);
		Connection conn = null;
		if ((conn = sc.login()) != null) {
			String cmd = "sh /" + remotePath + "/creatgit.sh " + remoteName;
			sc.exec(conn, cmd);
		} else
			throw new MyExcepition("连接远程仓库失败!");
	}

	/**
	 * 在本机指定目录建立本地远程仓库
	 * 
	 * @throws GitAPIException
	 * @throws IllegalStateException
	 * 
	 */
	public int createLocalRemote(String gitName) throws IllegalStateException,
			GitAPIException {
		File dir = new File(localPath + "/" + gitName + "/" + ".git");
		if (dir.exists())// 判断要创建的仓库名是否与已有仓库重名
			return 0;
		else {
			Git.init().setGitDir(dir).setDirectory(dir.getParentFile())
					.setBare(true).call();
			return 1;
		}
	}

	/**
	 * 用于创建Git文件目录,如果没有此目录会自动创建
	 * 
	 * @param gitName
	 * @throws GitAPIException
	 * @throws IllegalStateException
	 */
	public int creatLocalGit(String gitName) throws IllegalStateException,
			GitAPIException {
		File dir = new File(localPath + "/" + gitName + "/" + ".git");
		if (dir.exists())// 判断要创建的仓库名是否与已有仓库重名
			return 0;
		else {
			Git.init().setGitDir(dir).setDirectory(dir.getParentFile())
					.setBare(false).call();
			return 1;
		}
	}

	/**
	 * 用于Git-add文件到缓冲区
	 * 
	 * @param gitName
	 * @param fileName(如果输入‘.’,则代表仓库的所有文件都添加)
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws NoFilepatternException
	 */
	public void add(String gitName, String fileName)
			throws NoFilepatternException, GitAPIException, IOException {
		System.out.println("add----begin");
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.add().addFilepattern(fileName).call(); // 相当与git add
													// -A添加所有的变更文件git.add().addFilepattern("*.java")这种形式是不支持的
		// git.add().addFilepattern("src/main/java/").call(); //
		// 添加目录，可以把目录下的文件都添加到暂存区
		// jgit当前还不支持模式匹配的方式，例如*.java
		System.out.println("add----end");
	}

	/**
	 * 用于Git-rm -f将文件移出缓冲区和工作区,没有add直接rm会无效,有add但没有commit直接rm会git status看不到记录,
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws NoFilepatternException
	 */
	public void rm(String gitName, String fileName) throws IOException,
			NoFilepatternException, GitAPIException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.rm().addFilepattern(fileName).call();
	}

	/**
	 * 用于Git-commit文件到区
	 * 
	 * @param gitName
	 * @param message
	 * @return commitId
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws AbortedByHookException
	 * @throws WrongRepositoryStateException
	 * @throws ConcurrentRefUpdateException
	 * @throws UnmergedPathsException
	 * @throws NoMessageException
	 * @throws NoHeadException
	 */
	public String commit(String gitName, String message) throws IOException,
			NoHeadException, NoMessageException, UnmergedPathsException,
			ConcurrentRefUpdateException, WrongRepositoryStateException,
			AbortedByHookException, GitAPIException {
		System.out.println("commit----begin");
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		CommitCommand commitCommand = git.commit().setMessage(message)
				.setAllowEmpty(true);
		String commitId=commitCommand.call().getName();
		System.out.println("commit----end");
		return commitId;
	}

	/**
	 * 查看git文件夹状态(相当于git status)
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws NoWorkTreeException
	 */
	public StatusList getStatus(String gitName) throws IOException,
			NoWorkTreeException, GitAPIException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		StatusList sl = new StatusList();
		Status status = git.status().call(); // 返回的值都是相对工作区的路径，而不是绝对路径
		List<String> addFile = new ArrayList<String>();
		List<String> removeFile = new ArrayList<String>();
		List<String> modifiedFile = new ArrayList<String>();
		List<String> untrackedFile = new ArrayList<String>();
		List<String> confictingFile = new ArrayList<String>();
		List<String> missingFile = new ArrayList<String>();
		System.out.println(status.getAdded().isEmpty());
		status.getAdded().forEach(it -> addFile.add(it)); // git
															// add命令后会看到变化(one.doc),返回缓冲区里面的文件列表
		status.getRemoved().forEach(it -> removeFile.add(it)); // / git
																// rm命令会看到变化，从暂存区和工作区删除的文件列表,只有commit过的才会被返回
		status.getModified().forEach(it -> modifiedFile.add(it)); // 修改的文件列表(one.doc)
		status.getUntracked().forEach(it -> untrackedFile.add(it)); // 工作区新增的文件列表(未跟踪:打开文件没有关闭也会有这个状态)(one.doc)
		status.getConflicting().forEach(it -> confictingFile.add(it)); // 冲突的文件列表
		status.getMissing().forEach(it -> missingFile.add(it)); // 工作区删除的文件列表(即你手动删除的文件)
		sl.setAddFile(addFile);
		sl.setRemoveFile(removeFile);
		sl.setModifiedFile(modifiedFile);
		sl.setRemoveFile(removeFile);
		sl.setUntrackedFile(untrackedFile);
		sl.setConfictingFile(confictingFile);
		sl.setMissingFile(missingFile);
		return sl;
	}

	/**
	 * 查看git提交日志(相当于git log)
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws NoHeadException
	 */
	public List<LogEnity> getLog(String gitName) throws IOException,
			NoHeadException, GitAPIException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Iterable<RevCommit> result = git.log().setRevFilter(new RevFilter() {
			@Override
			// 将日志结构按提交人的名字进行筛选,这里选择不筛选
			public boolean include(RevWalk walker, RevCommit cmit)
					throws StopWalkException, MissingObjectException,
					IncorrectObjectTypeException, IOException {
				return cmit.getAuthorIdent().getName()
						.equals(cmit.getAuthorIdent().getName());
			}

			@Override
			public RevFilter clone() {
				return this;
			}
		}).call();
		List<LogEnity> ls = new ArrayList<LogEnity>();
		result.forEach(commit -> {
			LogEnity log = new LogEnity();
			PersonIdent authoIdent = commit.getAuthorIdent();
			log.setCommitAuthor(authoIdent.getName() + "     <"
					+ authoIdent.getEmailAddress() + ">");
			log.setCommitId(commit.getId().name());
			log.setCommitMassage(commit.getShortMessage());
			log.setCommitDate(format.format(authoIdent.getWhen()));
			ls.add(log);
		});
		return ls;
	}

	/**
	 * 回退到上一个版本(相当于git reset --hard HEAD^)
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws CheckoutConflictException
	 * 
	 */
	public void reset(String gitName) throws IOException,
			CheckoutConflictException, GitAPIException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		Repository repository = git.getRepository();
		RevWalk walk = new RevWalk(repository);
		Ref head = repository.findRef("HEAD");
		RevCommit revCommit = walk.parseCommit(head.getObjectId());
		String preVision = revCommit.getParent(0).getName();
		git.reset().setMode(ResetType.HARD).setRef(preVision).call();
		repository.close();
		walk.close();
	}

	/**
	 * 回退到指定版本(相当于git reset --hard 版本号)
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws CheckoutConflictException
	 * 
	 */
	public void reset(String gitName, String version)
			throws CheckoutConflictException, GitAPIException, IOException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.reset().setMode(ResetType.HARD).setRef(version).call();
	}

	/**
	 * 创建分支(相当于git branch <name> )
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws InvalidRefNameException
	 * @throws RefNotFoundException
	 * @throws RefAlreadyExistsException
	 * 
	 */
	public void createBranch(String gitName, String bname) throws IOException,
			RefAlreadyExistsException, RefNotFoundException,
			InvalidRefNameException, GitAPIException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.branchCreate().setName(bname).call();
	}

	/**
	 * 把某个分支合并到当前分支(相当于git merge <name>)
	 * 
	 * @throws Exception
	 * 
	 */
	public void mergeBranch(String gitName, String bname) throws Exception {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		MergeCommand mgCmd = git.merge();
		Ref ref = git.branchList().setContains(bname).call().get(0);
		mgCmd.include(ref); // ref被认为是对分支的引用
		MergeResult res = mgCmd.call(); // 实际上做合并
		if (res.getMergeStatus().equals(MergeResult.MergeStatus.CONFLICTING)) {
			throw new Exception("分支存在冲突");
			// 告知用户他必须处理冲突
		}
	}

	/**
	 * 删除分支(相当于git branch -d<name> )
	 * 
	 * @throws GitAPIException
	 * @throws CannotDeleteCurrentBranchException
	 * @throws NotMergedException
	 * @throws IOException
	 */
	public void deleteBranch(String gitName, String bname)
			throws NotMergedException, CannotDeleteCurrentBranchException,
			GitAPIException, IOException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.branchDelete().setBranchNames(bname).call();
	}

	/**
	 * 切换分支(相当于git checkout <name> 如果有文件没有commit就不会执行)
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 * @throws CheckoutConflictException
	 * @throws InvalidRefNameException
	 * @throws RefNotFoundException
	 * @throws RefAlreadyExistsException
	 */
	public void checkOutBranch(String gitName, String bname)
			throws IOException, RefAlreadyExistsException,
			RefNotFoundException, InvalidRefNameException,
			CheckoutConflictException, GitAPIException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.checkout().setName(bname).call();
	}

	/**
	 * 把获取当前仓库的所有分支名(相当于git branch )
	 * 
	 * @throws IOException
	 * @throws GitAPIException
	 */
	public List<String> showAllBranch(String gitName) throws IOException,
			GitAPIException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		List<Ref> refs = git.branchList().call();
		List<String> bs = new ArrayList<String>();
		for (Ref ref : refs) {
			bs.add(ref.getName().substring(11));
		}
		return bs;
	}

	/**
	 * 把远程仓库clone到指定目录(相当于git clone )
	 * 
	 * @throws TransportException
	 * @throws InvalidRemoteException
	 * @throws IOException
	 * @throws GitAPIException
	 */
	public int clone(String remoteName, String gitName)
			throws InvalidRemoteException, TransportException, GitAPIException {
		System.out.println("clone----begin");
		File filePath = new File(localPath + "/" + gitName);
		if (filePath.exists())// 判断要创建的仓库名是否与已有仓库重名
			return 0;
		else {
			String url = userName + "@" + remoteUrl + ":/" + remotePath + "/"
					+ remoteName + ".git";
			Git.cloneRepository()
					.setCloneAllBranches(true)
					.setURI(url)
					.setDirectory(filePath)
					.setCredentialsProvider(
							new UsernamePasswordCredentialsProvider(userName,
									password))
					.setTransportConfigCallback(getTransportConfigCallback())
					.call();
			System.out.println("clone----end");
			return 1;
		}

	}

	/**
	 * 把本地远程仓库clone到指定目录(相当于git clone 本地仓库)
	 * 
	 */
	public int cloneLocalRemote(String localRemotePath, String gitName)
			throws InvalidRemoteException, TransportException, GitAPIException {
		File filePath = new File(localPath + "/" + gitName);
		if (filePath.exists())// 判断要创建的仓库名是否与已有仓库重名
			return 0;
		else {
			Git.cloneRepository().setCloneAllBranches(true)
					.setURI(localRemotePath).setDirectory(filePath)
					.setTransportConfigCallback(getTransportConfigCallback())
					.call();
			return 1;
		}

	}

	/**
	 * 向远程仓库某个分支push((相当于git push)) 或者用于新建分支向远程仓库的推送
	 * 
	 * @throws GitAPIException
	 * @throws TransportException
	 * @throws InvalidRemoteException
	 * @throws IOException
	 */
	public void push(String gitName, String bName, String remoteName)
			throws InvalidRemoteException, TransportException, GitAPIException,
			IOException {
		System.out.println("push----begin");
		String url = userName + "@" + remoteUrl + ":/" + remotePath + "/"
				+ remoteName + ".git";
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		Ref ref = git.branchList().setContains(bName).call().get(0);
		git.push()
				.add(ref)
				.setCredentialsProvider(
						new UsernamePasswordCredentialsProvider(userName,
								password)).setRemote(url)
				.setTransportConfigCallback(getTransportConfigCallback())
				.call();
		git.close();
		System.out.println("push----end");
	}

	/**
	 * 向本地远程仓库某个分支push((相当于git push)) 或者用于新建分支向本地远程仓库的推送
	 * 
	 * @throws GitAPIException
	 * @throws TransportException
	 * @throws InvalidRemoteException
	 * @throws IOException
	 * 
	 */
	public void pushLocalRemote(String gitName, String bName,
			String localRemotePath) throws InvalidRemoteException,
			TransportException, GitAPIException, IOException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		Ref ref = git.branchList().setContains(bName).call().get(0);
		git.push().add(ref).setRemote(localRemotePath)
				.setTransportConfigCallback(getTransportConfigCallback())
				.call();
		git.close();
	}

	/**
	 * 从远程仓库拉取特定分支((相当于git pull))
	 * 
	 * @throws GitAPIException
	 * @throws TransportException
	 * @throws NoHeadException
	 * @throws RefNotAdvertisedException
	 * @throws RefNotFoundException
	 * @throws CanceledException
	 * @throws InvalidRemoteException
	 * @throws InvalidConfigurationException
	 * @throws WrongRepositoryStateException
	 * @throws IOException
	 * 
	 */
	public void pull(String gitName, String bName, String remoteName)
			throws WrongRepositoryStateException,
			InvalidConfigurationException, InvalidRemoteException,
			CanceledException, RefNotFoundException, RefNotAdvertisedException,
			NoHeadException, TransportException, GitAPIException, IOException {
		// String url = userName + "@" + remoteUrl + ":/" + remotePath + "/" +
		// remoteName + ".git";
		System.out.println("pull----begin");
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.pull()
				.setRemoteBranchName(bName)
				.setCredentialsProvider(
						new UsernamePasswordCredentialsProvider(userName,
								password))
				.setTransportConfigCallback(getTransportConfigCallback())
				.call();
		git.close();
		System.out.println("pull----end");
	}

	/**
	 * 从本地远程仓库拉取特定分支((相当于git pull))
	 * 
	 * @throws GitAPIException
	 * @throws TransportException
	 * @throws NoHeadException
	 * @throws RefNotAdvertisedException
	 * @throws RefNotFoundException
	 * @throws CanceledException
	 * @throws InvalidRemoteException
	 * @throws InvalidConfigurationException
	 * @throws WrongRepositoryStateException
	 * @throws IOException
	 * 
	 */
	public void pullLocalRemote(String gitName, String bName,
			String localRemotePath) throws WrongRepositoryStateException,
			InvalidConfigurationException, InvalidRemoteException,
			CanceledException, RefNotFoundException, RefNotAdvertisedException,
			NoHeadException, TransportException, GitAPIException, IOException {
		Git git = Git.open(new File(localPath + "/" + gitName + "/" + ".git"));
		git.pull().setRemoteBranchName(bName).setRemote(localRemotePath)
				.setTransportConfigCallback(getTransportConfigCallback())
				.call();
		git.close();
	}

	/**
	 * 判断本地是否有这个git仓库
	 * 
	 */
	public boolean isHave(String gitName) {
		System.out.println("isHave----begin");
		File f = new File(localPath + "/" + gitName);
		if (f.exists()) {
			System.out.println("isHave----end");
			return true;
		}
		return false;
	}

	/**
	 * 获取某个git仓库下的某个commit下的某个文件内容
	 * 
	 * @throws IOException
	 * 
	 */
	public byte[] readFileFromCommit(String gitName, String commitId, String path)
			throws IOException {
		Repository repository = Git.open(
				new File(localPath + "/" + gitName + "/" + ".git"))
				.getRepository();
		RevCommit revCommit = buildRevCommit(repository, commitId);
		RevTree tree = revCommit.getTree();
		// System.out.println("Having tree: " + tree);

		// now try to find a specific file
		try (TreeWalk treeWalk = new TreeWalk(repository)) {
			treeWalk.addTree(tree);
			treeWalk.setRecursive(true);
			treeWalk.setFilter(PathFilter.create(path));
			if (!treeWalk.next()) {
				throw new IllegalStateException("Did not find expected file "
						+ path);
			}
			ObjectId objectId = treeWalk.getObjectId(0);
			ObjectLoader loader = repository.open(objectId);
			byte[] fileByte = loader.getBytes();
			return fileByte;
		}
	}

	/**
	 * 获取某个git仓库下的所有commitId(由新到旧)
	 * 
	 * @throws IOException
	 * 
	 */
	public List<String> listCommitId(String gitName) throws IOException {
		Repository repository = Git.open(
				new File(localPath + "/" + gitName + "/" + ".git"))
				.getRepository();
		Collection<Ref> allRefs = repository.getAllRefs().values();
		List<String> commitIds = new LinkedList<String>();
		// a RevWalk allows to walk over commits based on some filtering that is
		// defined
		try (RevWalk revWalk = new RevWalk(repository)) {
			for (Ref ref : allRefs) {
				revWalk.markStart(revWalk.parseCommit(ref.getObjectId()));
			}
			for (RevCommit commit : revWalk) {
				commitIds.add(commit.getName());
			}
		}
		return commitIds;
	}

	/**
	 * 获取某个git仓库下的某次提交的某个文件夹下的文件列表
	 * 
	 */
	public List<String> listFilesOfCommit(String gitName, String commitId, String path)
			throws IOException {
		Repository repository = Git.open(
				new File(localPath + "/" + gitName + "/" + ".git"))
				.getRepository();
		List<String> paths = readElementsAt(repository, commitId, path);
		return paths;
	}

	private static List<String> readElementsAt(Repository repository,
			String commit, String path) throws IOException {
		RevCommit revCommit = buildRevCommit(repository, commit);

		// and using commit's tree find the path
		RevTree tree = revCommit.getTree();
		// System.out.println("Having tree: " + tree + " for commit " + commit);

		List<String> items = new ArrayList<>();

		// shortcut for root-path
		if (path.isEmpty()) {
			try (TreeWalk treeWalk = new TreeWalk(repository)) {
				treeWalk.addTree(tree);
				treeWalk.setRecursive(false);
				treeWalk.setPostOrderTraversal(false);

				while (treeWalk.next()) {
					items.add(treeWalk.getPathString());
				}
			}
		} else {
			// now try to find a specific file
			try (TreeWalk treeWalk = buildTreeWalk(repository, tree, path)) {
				if ((treeWalk.getFileMode(0).getBits() & FileMode.TYPE_TREE) == 0) {
					throw new IllegalStateException(
							"Tried to read the elements of a non-tree for commit '"
									+ commit + "' and path '" + path
									+ "', had filemode "
									+ treeWalk.getFileMode(0).getBits());
				}

				try (TreeWalk dirWalk = new TreeWalk(repository)) {
					dirWalk.addTree(treeWalk.getObjectId(0));
					dirWalk.setRecursive(false);
					while (dirWalk.next()) {
						items.add(dirWalk.getPathString());
					}
				}
			}
		}

		return items;
	}

	private static TreeWalk buildTreeWalk(Repository repository, RevTree tree,
			final String path) throws IOException {
		TreeWalk treeWalk = TreeWalk.forPath(repository, path, tree);

		if (treeWalk == null) {
			throw new FileNotFoundException("Did not find expected file '"
					+ path + "' in tree '" + tree.getName() + "'");
		}

		return treeWalk;
	}

	private static RevCommit buildRevCommit(Repository repository, String commit)
			throws IOException {
		// a RevWalk allows to walk over commits based on some filtering that is
		// defined
		try (RevWalk revWalk = new RevWalk(repository)) {
			return revWalk.parseCommit(ObjectId.fromString(commit));
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		File filePath = new File(localPath);
		if (!filePath.exists())// 如果文件夹不存在
			filePath.mkdir();// 创建文件夹
	}
}
